home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_100 / 105_01 / randomx.c < prev    next >
Text File  |  1984-06-03  |  12KB  |  488 lines

  1. /*
  2.     random file routines
  3.  
  4.     pre-usersgroup release by special request, this package will
  5. be polished and extended before general distribution. address any ideas,
  6. requests, bug reports etc. to:
  7.  
  8.     Steve Passe
  9.     New Ideas
  10.     2500 S. Pennsylvania St.
  11.     Denver, CO    80210
  12.  
  13.     (303) 761-4378  who knows when?  your best bet is in the evening
  14.  
  15.     some notes on these functions-
  16.  
  17.     since the buffer is completely written to disk even though only
  18. one byte may have been added, a program that uses the entire 8 megabyte
  19. range could fill a disk with 240 byes (assuming a declared buffer size
  20. of 1 k and even distribution of those bytes over the entire range). one
  21. solution would be to keep the buffer size down to 1 sector. the best is
  22. to be reasonable with the address range of your program. logically a file
  23. of 8 megabytes could be spread over x disks if necessary.
  24.  
  25.     these functions need:    1.cp/m 2.x
  26.                 2.alloc() installed in the stdlib
  27.                 3:_allocp = NULL; in main
  28.                 4.the undocumented (but existing)
  29.                     functions rsrec()
  30.                           rcfsiz()
  31.                           rtell()
  32.                           rseek()
  33.                           rread()
  34.                           rwrite()
  35.                   the code for these is in deff2a.asm
  36.                   and is the only existing doc for them
  37.  
  38.     the buffer size is declared on opening the file and is maintained
  39. in a space provided by alloc(). it can be any length from 1 sector to
  40. memory size available (keep in mind the above note on buffer size as affected
  41. by random writes). if your needs change you can close and reopen with a diff-
  42. erent size buffer. closes AUTOMATICALLY flush the buffer, no explicit call
  43. of rflush() needed.
  44.  
  45.     see pages 164-169 of 'the c programming language' for insight
  46. into the madness of the package
  47.  
  48. */
  49.  
  50. #include "a:std.h"        /* bdscio.h plus my own system defs */
  51.  
  52. /*
  53.     routines to parallel the buffered input and output routines,
  54. allowing completely random buffered read and writes to a file
  55.  
  56.     these are closely modeled on the routines by Leor for
  57. buffered sequential files.
  58.  
  59. functions - 
  60.  
  61.     rcreat(filename, fp, mode, secs)
  62.         creat an as yet non-existant file
  63.     ropen(filename, fp, mode, secs)
  64.         open an already existing file
  65.     rclose(fp)
  66.         close a random file (takes care of all 'flushing')
  67.     rflush(fp)
  68.         'flush' a random file buffer to disk
  69.     fseek(fp, offset, origin)
  70.         set the 'byte-pointer' to a specific byte within the
  71.             8 megabyte range of 2.2
  72.     ftell(fp)
  73.         report the current position of the 'byte-pointer' in
  74.             an open file
  75.     rgetc(fp)
  76.         returns the byte pointed at by the 'byte-pointer'
  77.             and bumps the pointer by 1
  78.     rputc(c, fp)
  79.         puts the byte 'c' in the file at the position defined
  80.             by the 'byte-pointer', bumps the pointer by 1
  81.  
  82.     the next four are not contained in this package. to impliment
  83. take the code of their cousins (getw(),putw(),fprintf(),fscanf()) and
  84. replace all instances of getc() with rgetc(), putc() with rputc().
  85. although I haven't tried this yet they should work properly as all
  86. modularized c code does.
  87.  
  88.     rgetw(fp)
  89.     rputw(w, fp)
  90.     rprintf(fp, format, arg1, arg2,...)
  91.     rscanf(fp, format, arg1, arg2,...)
  92.  
  93.     the next four again are unwritten. rgetl() and rputl() will
  94. essentially be fgets() and fputs() modified as in the previous example.
  95. the change to 'l' is to denote the fact that they work with 'lines'
  96. in a cp/m file environment. these two would be used to diddle with cp/m
  97. compatible files. rgets() and rputs() are more straightforward functions
  98. that merely handle strings as c intended. these will be included in the
  99. package for distribution by the users group.
  100.  
  101.     rgets(str, fp)
  102.     rputs(str, fp)
  103.     rgetl(line, fp)
  104.     rputl(line, fp)
  105.  
  106.  the following four functions (names) are as yet unwritten but are
  107. reserved for use by this package. again, they will be written for the
  108. distribution package.
  109.  
  110.     rget(fp, destination, nbyt)
  111.     rput(fp, source, nbyt)
  112.     rgetstruct(fp, destination, structsiz)
  113.     rputstruct(fp, source, structsiz)
  114. */
  115.  
  116. /*
  117.     this is the structure that controls the show. such a structure
  118.     must be declared for each file in main. also, very important, be
  119.     sure to include an initialization of _allocp = NULL; in main()
  120.     before doing anything else.
  121. */
  122.  
  123. struct _file {
  124.     int _rfd;        /* file descripter */
  125.     int _secs;        /* # of sectors in buffer */
  126.     unsigned _frstsec;    /* first sector in buffer */
  127.     unsigned _cursec;    /* cp/m current random sec */
  128.     byte _curbyt;        /* current random byte */
  129.     byte *_nxtbyt;        /* next byte to be processed */
  130.     byte *_bufbase;        /* location of base */
  131.     byte *_pastbuf;        /* first byte beyond end of buffer */
  132.     char _mode;        /* read, write, append, or direct */
  133.     int _update;        /* buffer modified flag */
  134.     unsigned _curblk;    /* currently addressed block */
  135.     int _blksiz;        /* size of a logical block */
  136. };
  137.  
  138. /*
  139.     purge any old copies, creat and open 'filename', buffer
  140. size equal to secs * size of one sector, mode of write (from
  141. beginning of file), append (write at end of file), or direct
  142. (read or write, starting at beginning of file, random access
  143. to any part of file). read not allowed as you can't read a
  144. new file.
  145. */
  146.  
  147. struct *
  148. rcreat(filename, fp, mode, secs)
  149. char *filename;
  150. struct _file *fp;
  151. char mode;
  152. int secs;
  153. {
  154.     int fd;
  155.     struct *ropen();
  156.  
  157.     switch (mode) {
  158.     case 'r':    return NULL;
  159.     case 'w':
  160.     case 'a':
  161.     case 'd':
  162.         if ((fd = creat(filename)) < 0 ) return NULL;
  163.         fabort(fd);
  164.         return ropen(filename, fp, mode, secs);
  165.     default:
  166.         return NULL;
  167.     }
  168. }
  169. /*
  170.     open 'filename' buffer in space provided by alloc(), setup
  171. fp, buffer of size SECSIZ * secs
  172. */
  173.  
  174. struct *
  175. ropen(filename, fp, mode, secs)
  176. char *filename;
  177. struct _file *fp;
  178. char mode;
  179. int secs;
  180. {
  181.     byte *alloc();
  182.     unsigned rcfsiz(), rsrec(), ftell();
  183.  
  184.     switch (mode) {
  185.     case 'r':
  186.         fp -> _rfd = open(filename, 0);
  187.         break;
  188.     case 'w':
  189.     case 'a':
  190.     case 'd':
  191.         fp -> _rfd = open(filename, 2);
  192.         break;
  193.     default:
  194.         return NULL;
  195.     }
  196.     if (fp -> _rfd < 0) return NULL;
  197.  
  198.     if ((fp -> _bufbase = alloc(secs * SECSIZ)) == 0) return NULL;
  199.     fp -> _secs = secs;
  200.     fp -> _nxtbyt = fp -> _bufbase;
  201.     fp -> _pastbuf = fp -> _bufbase + (secs * SECSIZ);
  202.     fp -> _mode = mode;
  203.     fp -> _frstsec = (mode == 'a') ?
  204.         rcfsiz(fp->_rfd) : rsrec(fp->_rfd);
  205.     ftell(fp);
  206.     if (_fillbuf(fp) < 0 ) return NULL;
  207.     return fp;
  208. }
  209.  
  210. /*
  211.     flushes, then closes the random file at fp
  212. */
  213.  
  214. rclose(fp)
  215. struct _file *fp;
  216. {
  217.     if (rflush(fp) < 0 ) return ERROR;
  218.     free(fp->_bufbase);
  219.     return close(fp -> _rfd);
  220. }
  221. /*
  222.     fills buffer pointed at by fp->_bufbase, with file fp->_rfd,
  223. with fp->_secs sectors, starting with cp/m random record field
  224. fseek calls this after updating cp/m's rrf and fp's pointers (if
  225. necessary because seek is out of buffer area)
  226. */
  227.  
  228. _fillbuf(fp)
  229. struct _file *fp;
  230. {
  231.     int fd, secs, got;
  232.     byte *base;
  233.     unsigned rseek();
  234.  
  235.     fd = fp -> _rfd;
  236.     secs = fp -> _secs;
  237.     base = fp -> _bufbase;
  238.  
  239.     while  (secs -= (got = rread(fd, base, secs))) {
  240.         if ((got > 1000) OR (got == -1)) return ERROR;
  241.         setmem((base += (got * SECSIZ)), SECSIZ, 0);
  242.         base += SECSIZ;
  243.         rseek(fd, 1, 1);
  244.         --secs;
  245.     }
  246.     fp -> _update = NO;
  247.     return OK;
  248. }
  249. /*
  250.     flushes the buffer fp->_bufbase if open for writing AND
  251. fp->_update shows the buffer has indeed been written to since
  252. last _fillbuf call. ignores flushes of i/o devices
  253. */
  254.  
  255. rflush(fp)
  256. struct _file *fp;
  257. {
  258.     unsigned rseek();
  259.  
  260.     if ((fp < 4) OR (fp->_mode == 'r') OR (fp->_update == NO))
  261.         return OK;
  262.     if (rseek(fp -> _rfd, fp -> _frstsec, 0) < 0) return ERROR;
  263.     if (rwrite(fp->_rfd, fp->_bufbase, fp->_secs) != fp->_secs)
  264.         return ERROR;
  265.     fp -> _update = NO;
  266.     return OK;
  267. }
  268. /*
  269.     sets '_nxtbyt' of 'fp' to 'sector's and 'byt's from
  270. 'origin' , returns cp/m current random sector.
  271. */
  272.  
  273. unsigned
  274. fseek(fp, sector, byt, origin)
  275. struct _file *fp;
  276. unsigned sector;
  277. byte byt;
  278. int origin;
  279. {
  280.     unsigned ftell(), rseek(), rcfsiz();
  281.  
  282.     switch (origin) {
  283.     case 0:    break;
  284.     case 1:    sector += ftell(fp);
  285.         break;
  286.     case 2:    sector += rcfsiz(fp->_rfd);
  287.         break;
  288.     default:
  289.         return ERROR;
  290.     }
  291.     if ((sector >= fp->_frstsec) AND
  292.         (sector < (fp->_frstsec + fp->_secs))) {
  293.         fp->_nxtbyt = (sector - fp->_frstsec)*SECSIZ
  294.             + byt + fp->_bufbase;
  295.         return ftell(fp);
  296.     }
  297.